<?php

final class ZFrame {

	const
		VERSION            = "0.1",
		FRONT_ROOT_DIR     = "../php/front/",
		PAGE_NOT_FOUND_URL = "404-page.xml"
		;

	private
	    $sUrl,
		$oDocument,
		$oXMLHelper
		;

	public function __construct($sUrl) {

        $this->sUrl = $sUrl;

	}

	public function run() {

        ob_start();

        try {

            $this->initReqistry();

            libxml_use_internal_errors(true);

		    $this->createDocument();
            $this->processBlocks();

            print($this->processTemplate());

            $aXmlErrors = libxml_get_errors();

            if(count($aXmlErrors)) {

                throw new Exception_Xml($aXmlErrors[0]);
                libxml_clear_errors();

            }

            ob_end_flush();

        }
        catch(Exception_DocumentFileNotFound $oException) {

            if($this->sUrl == self::PAGE_NOT_FOUND_URL) {
                die("Page for \"page not found\" not found");
            }

            ob_clean();

            $oZFrame = new ZFrame(self::PAGE_NOT_FOUND_URL);
            $oZFrame->run();

        }
        catch(Exception $oException) {

            ob_end_clean();
            die("<pre>" . $oException->getMessage() . "</pre>");

        }

	}

	private function initReqistry() {

        Registry::getInstance()->reset();
	    Registry::getInstance()->set("holder-manager", new HolderManager());

    }

	private function createDocument() {

		$this->oXMLHelper = new XMLHelper();
		$this->oDocument = $this->oXMLHelper->createDocumentFromFile(self::FRONT_ROOT_DIR . $this->sUrl);

	}

	private function processBlocks() {

		$aNodeBlocks = $this->oDocument->getElementsByTagName("block");
		for($i = 0; $i < $aNodeBlocks->length; $i++) {
			if($aNodeBlocks->item($i)->hasAttribute("method")) {
				if($this->processBlockNode($aNodeBlocks->item($i))) {
					$i--;
				}
			}
		}

	}

	private function processBlockNode(DOMNode $oNodeBlock) {

        try {

            $oBlock = new Block($oNodeBlock);

            $this->oXMLHelper->replaceNodeFromString(
                $oNodeBlock,
                $oBlock->process()
                );

			return true;

        }
        catch(XMLSerializable $oException) {
        	libxml_clear_errors();
            $this->oXMLHelper
                ->removeChildren($oNodeBlock)
                ->addNodeFromString(
                    $oNodeBlock,
                    $oException->toXML()
                    );
        }

        return false;

    }

	private function processTemplate() {

		if($this->oDocument->childNodes->item(0)->nodeType == XML_PI_NODE) {

			$aPIData = $this->oXMLHelper->getPIData($this->oDocument->childNodes->item(0));
			$oTemplateProcessor = new TemplateProcessor(self::FRONT_ROOT_DIR . $aPIData["href"]);

			return $oTemplateProcessor->process($this->oDocument);

		}

		header("Content-type: text/xml");

		return $this->oXMLHelper->documentToString();

	}


}

?>